import { defineConfig, loadEnv, ConfigEnv, UserConfig } from "vite";
import { createHtmlPlugin } from "vite-plugin-html";
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";
import { wrapperEnv } from "./src/utils/getEnv";
import { visualizer } from "rollup-plugin-visualizer";
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
import viteCompression from "vite-plugin-compression";
import VueSetupExtend from "vite-plugin-vue-setup-extend";
import eslintPlugin from "vite-plugin-eslint";
import vueJsx from "@vitejs/plugin-vue-jsx";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import fsWrite from "./src/config/writeLangFile";
import { removeGoJsWatermark } from "./src/config/gojs";
import importToCDN from "vite-plugin-cdn-import";
import externalGlobals from "rollup-plugin-external-globals";

const externalGlobalsObj = {
	vue: "Vue",
	"vue-demi": "VueDemi",
	"element-plus": "ElementPlus",
	echarts: "Echarts"
};
//输出gojs水印
removeGoJsWatermark();

// @see: https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
	const env = loadEnv(mode, process.cwd());
	const viteEnv = wrapperEnv(env);

	//国际化词条处理
	// if (mode == "production") {
	//将词条拆分到不同文件
	fsWrite();
	// }

	return {
		base: "./",
		resolve: {
			alias: {
				"@": resolve(__dirname, "./src"),
				"@public": resolve(__dirname, "./public"),
				"vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js"
			},
			dedupe: ["vue"]
		},
		css: {
			preprocessorOptions: {
				scss: {
					//fix Error: @use rules must be written before any other rules
					additionalData: `@use "@/styles/var.scss" as *;`
				}
			}
		},
		server: {
			port: viteEnv.VITE_PORT,
			open: true,
			cors: true,
			proxy: {
				"/api": {
					target: viteEnv.VITE_API_URL,
					// target: "http://172.16.22.81:9000",
					changeOrigin: true
				}
			}
		},
		plugins: [
			viteEnv.VITE_CDN
				? importToCDN({
						modules: [
							{
								name: "vue",
								var: "Vue",
								path: "https://unpkg.com/vue@3.2.45/dist/vue.global.js"
							},
							{
								name: "vue-demi",
								var: "VueDemi",
								path: "https://unpkg.com/vue-demi@0.14.5"
							},
							{
								name: "element-plus",
								var: "ElementPlus",
								path: "https://unpkg.com/element-plus@2.3.5/dist/index.full.js",
								css: "https://unpkg.com/element-plus@2.3.5/dist/index.css"
							},
							{
								name: "echarts",
								var: "echarts",
								path: "https://cdn.staticfile.org/echarts/5.4.1/echarts.min.js"
							}
						]
				  })
				: "",

			vue(),
			createHtmlPlugin({
				inject: {
					data: {
						title: viteEnv.VITE_GLOB_APP_TITLE
					}
				}
			}),
			// * 使用 svg 图标
			createSvgIconsPlugin({
				iconDirs: [resolve(process.cwd(), "src/assets/icons")],
				symbolId: "icon-[dir]-[name]"
			}),
			// * EsLint 报错信息显示在浏览器界面上
			eslintPlugin(),
			// * vite 可以使用 jsx/tsx 语法
			vueJsx(),
			// * name 可以写在 script 标签上
			VueSetupExtend(),
			// * 是否生成包预览(分析依赖包大小,方便做优化处理)
			viteEnv.VITE_REPORT && visualizer(),
			// * gzip compress
			viteEnv.VITE_BUILD_GZIP &&
				viteCompression({
					verbose: true,
					disable: false,
					threshold: 1024,
					algorithm: "gzip",
					ext: ".gz"
				}),
			// * demand import element
			AutoImport({
				// 第三方组件库的解析器
				resolvers: [ElementPlusResolver()],
				// 生成自动导入的TS声明文件
				dts: "./auto-imports.d.ts",
				imports: ["vue"],
				eslintrc: {
					enabled: false, // 1、改为true用于生成eslint配置。2、生成后改回false，避免重复生成消耗
					filepath: "./.eslintrc-auto-import.json", // Default `./.eslintrc-auto-import.json`
					globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
				}
			}),
			viteEnv.VITE_CDN
				? {
						...externalGlobals(externalGlobalsObj),
						enforce: "post",
						apply: "build"
				  }
				: {},
			Components({
				dirs: ["src/components"], // 要导入组件的目录路径
				extensions: ["vue"], //配置需要将哪些后缀类型的文件进行自动按需引入
				deep: true, // 搜索子目录
				include: [/\.vue$/, /\.vue\?vue/], // 只识别vue文件
				dts: "./components.d.ts", //dts: false, // 不使用ts
				resolvers: [
					ElementPlusResolver({
						// 使用unplugin-vue-components按需加载样式，开发环境会导致项目异常卡顿
						// 导致原因：vite会预加载style，当首次启动 vite 服务时会对 style 进行依赖预构建，，因为element-plus的按需样式会导入大量style文件，导致页面会卡住直至style构建完成
						// https://github.com/antfu/unplugin-vue-components/issues/361
						// 这里开发环境不按需加载样式，生产环境才按需加载样式
						importStyle: mode === "development" ? false : "sass"
					})
				]
			}),
			// 使用unplugin-vue-components按需加载样式，开发环境会导致项目异常卡顿
			// 导致原因：vite会预加载style，当首次启动 vite 服务时会对 style 进行依赖预构建，，因为element-plus的按需样式会导入大量style文件，导致页面会卡住直至style构建完成
			// https://github.com/antfu/unplugin-vue-components/issues/361
			// 这里自定义一个vite插件，更改src/main.js内容，开发环境全局引入样式
			{
				name: "import-element-plus-style",
				transform(code, id) {
					if (/src\/main.js$/.test(id)) {
						if (mode === "development") {
							return {
								code: `${code};import 'element-plus/dist/index.css';`,
								map: null
							};
						} else {
							return {
								code: `${code};import 'element-plus/theme-chalk/src/message-box.scss';import 'element-plus/theme-chalk/src/message.scss';`,
								map: null
							};
						}
					}
				}
			}
		],
		// * 打包去除 console.log && debugger
		esbuild: {
			pure: viteEnv.VITE_DROP_CONSOLE ? ["console.log", "debugger"] : []
		},
		build: {
			sourcemap: false,
			outDir: "dist",
			chunkSizeWarningLimit: 1024,
			minify: "terser",
			cssCodeSplit: true, // 如果设置为false，整个项目中的所有 CSS 将被提取到一个 CSS 文件中
			terserOptions: {
				compress: {
					// warnings: false,
					drop_console: true, //打包时删除console
					drop_debugger: true, //打包时删除 debugger
					pure_funcs: ["console.log"]
				},
				output: {
					// 去掉注释内容
					comments: true
				}
			},
			rollupOptions: {
				output: {
					// manualChunks: {
					// 	// 拆分代码，这个就是分包，配置完后自动按需加载，现在还比不上webpack的splitchunk，不过也能用了。
					// 	vue: ["vue", "vue-router"],
					// 	echarts: ["echarts"]
					// },
					chunkFileNames: "assets/js/[name]-[hash].js",
					entryFileNames: "assets/js/[name]-[hash].js",
					assetFileNames: "assets/[ext]/[name]-[hash].[ext]"
				}
			}
		}
	};
});
